<template>
	<div class="md-editor-container">
		<MdEditor
			v-model="content"
			:toolbars="toolbars"
			:preview-only="preview === 'preview'"
			:code-theme="codeTheme"
			:theme="currentTheme"
			:language="language"
			:style="{ height }"
			:disabled="disabled"
			:readonly="readonly"
			:showToolbarName="showToolbarName"
			:toolbarsExclude="toolbarsExclude"
			@onChange="handleChange"
			@onSave="handleSave"
			@onUploadImg="handleUploadImg"
		>
			<template #defToolbars>
				<NormalToolbar title="PDF导出" @onClick="handleCustomPdfExport">
					<el-tooltip class="box-item" effect="dark" content="PDF导出">
						<el-icon><Document /></el-icon>
					</el-tooltip>
				</NormalToolbar>
			</template>
		</MdEditor>
	</div>
</template>

<script setup lang="ts" name="MdEditor">
import { ref, watch, computed, onMounted, onUnmounted } from 'vue';
import { Document } from '@element-plus/icons-vue';
import { MdEditor, NormalToolbar } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
import { Local } from '/@/utils/storage';
import ElMessage from 'element-plus/es/components/message/index';
import html2pdf from 'html2pdf.js';
import MarkdownIt from 'markdown-it';

// 定义组件属性
const props = defineProps({
	// 编辑器内容
	modelValue: {
		type: String,
		default: '',
	},
	// 编辑器高度
	height: {
		type: String,
		default: '400px',
	},
	// 预览模式
	preview: {
		type: String as () => 'live' | 'edit' | 'preview',
		default: 'live',
	},
	// 代码主题
	codeTheme: {
		type: String as () => 'github' | 'atom-one-dark' | 'vs2015' | 'monokai' | 'dracula',
		default: 'github',
	},
	// 编辑器主题
	theme: {
		type: String as () => 'light' | 'dark',
		default: 'light',
	},
	// 语言
	language: {
		type: String,
		default: 'zh-CN',
	},
	// 是否禁用
	disabled: {
		type: Boolean,
		default: false,
	},
	// 只读
	readonly: {
		type: Boolean,
		default: false,
	},
	// 占位符
	placeholder: {
		type: String,
		default: '请输入内容...',
	},
	// 是否显示工具栏名称
	showToolbarName: {
		type: Boolean,
		default: false,
	},
	// 是否显示PDF导出按钮
	showPdfExport: {
		type: Boolean,
		default: true,
	},
	// PDF导出文件名
	pdfFileName: {
		type: String,
		default: 'document.pdf',
	},
});

// 定义事件
const emit = defineEmits(['update:modelValue', 'change', 'save', 'upload-img', 'pdf-export']);

// 响应式数据
const content = ref(props.modelValue || '');

// 当前主题状态
const isDarkMode = ref(false);

// 计算当前主题
const currentTheme = computed(() => {
	// 如果props中指定了主题，优先使用props的主题
	if (props.theme !== 'light') {
		return props.theme;
	}
	// 否则根据系统暗黑模式状态决定
	return isDarkMode.value ? 'dark' : 'light';
});

// 检测暗黑模式状态
const checkDarkMode = () => {
	const htmlEl = document.documentElement;
	isDarkMode.value = htmlEl.hasAttribute('data-theme') && htmlEl.getAttribute('data-theme') === 'dark';
};

// 监听主题变化
const observeThemeChange = () => {
	const observer = new MutationObserver((mutations) => {
		mutations.forEach((mutation) => {
			if (mutation.type === 'attributes' && mutation.attributeName === 'data-theme') {
				checkDarkMode();
			}
		});
	});

	observer.observe(document.documentElement, {
		attributes: true,
		attributeFilter: ['data-theme'],
	});

	return observer;
};

// 工具栏配置
const toolbars = computed(() => {
	const baseToolbars = [
		'bold' as const,
		'underline' as const,
		'italic' as const,
		'-' as const,
		'title' as const,
		'strikeThrough' as const,
		'sub' as const,
		'sup' as const,
		'quote' as const,
		'unorderedList' as const,
		'orderedList' as const,
		'task' as const,
		'-' as const,
		'codeRow' as const,
		'code' as const,
		'link' as const,
		'image' as const,
		'table' as const,
		'mermaid' as const,
		'katex' as const,
		'-' as const,
		'revoke' as const,
		'next' as const,
		'=' as const,
		'pageFullscreen' as const,
		'fullscreen' as const,
		'preview' as const,
		'htmlPreview' as const,
		'catalog' as const,
	];

	// 添加自定义工具栏按钮的占位符
	baseToolbars.push('-' as const);
	baseToolbars.push(0 as any); // 0 表示第一个自定义工具栏按钮

	return baseToolbars;
});

// 排除的工具栏按钮
const toolbarsExclude = computed(() => []);

// 内容变化处理
const handleChange = (value: string) => {
	content.value = value;
	emit('update:modelValue', value);
	emit('change', value);
};

// 保存处理
const handleSave = (value: string) => {
	emit('save', value);
};

// 图片上传处理
const handleUploadImg = async (files: FileList, callback: (urls: string[]) => void) => {
	try {
		const urls: string[] = [];

		for (let i = 0; i < files.length; i++) {
			const file = files[i];
			const formData = new FormData();
			formData.append('file', file);

			const response = await fetch('/api/_file/uploadImage', {
				method: 'POST',
				headers: {
					Authorization: `Bearer ${Local.get('token')}`,
				},
				body: formData,
			});

			if (response.ok) {
				const result = await response.json();
				urls.push(result.data || result.url || '');
			}
		}

		callback(urls);
	} catch (error) {
		console.error('图片上传失败:', error);
		callback([]);
	}
};

// 复用 markdown-it 实例
const mdParser = new MarkdownIt({
	html: true,
	linkify: true,
	typographer: true,
});

// PDF 样式常量
const pdfStyle = `
  <style>
    .pdf-export-html { max-width: 800px; margin: 0 auto; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; line-height: 1.6; color: #333; }
    .pdf-export-html h1, .pdf-export-html h2, .pdf-export-html h3, .pdf-export-html h4, .pdf-export-html h5, .pdf-export-html h6 {
      margin-top: 1.5em; margin-bottom: 0.5em; font-weight: bold;
    }
    .pdf-export-html h1 { font-size: 2em; }
    .pdf-export-html h2 { font-size: 1.5em; }
    .pdf-export-html h3 { font-size: 1.3em; }
    .pdf-export-html h4 { font-size: 1.1em; }
    .pdf-export-html p { margin-bottom: 1em; }
    .pdf-export-html ul, .pdf-export-html ol { margin-bottom: 1em; padding-left: 2em; }
    .pdf-export-html li { margin-bottom: 0.5em; }
    .pdf-export-html blockquote {
      border-left: 4px solid #ddd; padding-left: 1em; margin: 1em 0; color: #666;
    }
    .pdf-export-html code {
      background-color: #f5f5f5; padding: 2px 4px; border-radius: 3px; font-family: Monaco, Consolas, 'Courier New', monospace;
    }
    .pdf-export-html pre {
      background-color: #f5f5f5; padding: 1em; border-radius: 5px; overflow-x: auto; margin: 1em 0;
    }
    .pdf-export-html table {
      border-collapse: collapse; width: 100%; margin: 1em 0;
    }
    .pdf-export-html th, .pdf-export-html td {
      border: 1px solid #ddd; padding: 8px; text-align: left;
    }
    .pdf-export-html th {
      background-color: #f5f5f5; font-weight: bold;
    }
    .pdf-export-html img {
      max-width: 100%; height: auto;
    }
  </style>
`;

// markdown 转 html 工具函数
function markdownToHtml(markdown: string): string {
	try {
		const htmlContent = mdParser.render(markdown);
		return `<div class=\"pdf-export-html\">${htmlContent}</div>`;
	} catch (error) {
		console.error('Markdown转换失败:', error);
		return `<pre>${markdown}</pre>`;
	}
}

// 生成并下载PDF
const generateAndDownloadPdf = async (html: string) => {
	try {
		const element = document.createElement('div');
		element.innerHTML = pdfStyle + html;
		element.style.padding = '0';
		// 配置PDF选项
		const opt = {
			margin: [10, 10, 10, 10],
			filename: props.pdfFileName,
			image: { type: 'jpeg', quality: 0.98 },
			html2canvas: {
				scale: 2,
				useCORS: true,
				allowTaint: true,
				letterRendering: true,
			},
			jsPDF: {
				unit: 'mm',
				format: 'a4',
				orientation: 'portrait',
			},
		};
		await html2pdf().set(opt).from(element).save();
	} catch (error) {
		console.error('PDF生成失败:', error);
		throw error;
	}
};

// 自定义PDF导出处理
const handleCustomPdfExport = async () => {
	if (!content.value?.trim()) {
		ElMessage.warning('内容为空，无法导出PDF');
		return;
	}
	try {
		ElMessage.info('正在生成PDF，请稍候...');
		const htmlContent = markdownToHtml(content.value);
		await generateAndDownloadPdf(htmlContent);
		emit('pdf-export', {
			html: htmlContent,
			fileName: props.pdfFileName,
			content: content.value,
		});
		ElMessage.success('PDF导出成功');
	} catch (error) {
		console.error('PDF导出失败:', error);
		ElMessage.error('PDF导出失败，请稍后重试');
	}
};

// 监听 modelValue 变化
watch(
	() => props.modelValue,
	(newValue) => {
		content.value = newValue || '';
	},
	{ immediate: true }
);

// 监听禁用状态变化
watch(
	() => props.disabled,
	(newValue) => {
		// 这里可以添加禁用逻辑
	},
	{ immediate: true }
);

// 监听主题变化
watch(
	() => currentTheme.value,
	(newTheme) => {
		// 主题变化时的处理逻辑
	},
	{ immediate: true }
);

// 组件挂载时初始化
onMounted(() => {
	checkDarkMode();
	const observer = observeThemeChange();

	// 保存observer引用以便清理
	(window as any).mdEditorThemeObserver = observer;
});

// 组件卸载时清理
onUnmounted(() => {
	if ((window as any).mdEditorThemeObserver) {
		(window as any).mdEditorThemeObserver.disconnect();
	}
});
</script>

<style scoped>
.md-editor-container {
	width: 100%;
}

.md-editor-container :deep(.md-editor) {
	border: 1px solid #dcdfe6;
	border-radius: 4px;
}

.md-editor-container :deep(.md-editor:hover) {
	border-color: #c0c4cc;
}

.md-editor-container :deep(.md-editor:focus-within) {
	border-color: #409eff;
}

.md-editor-container :deep(.md-editor-toolbar) {
	border-bottom: 1px solid #dcdfe6;
	background-color: #fafafa;
}

.md-editor-container :deep(.md-editor-content) {
	background-color: #fff;
}

.md-editor-container :deep(.md-editor-input) {
	background-color: #fff;
}

.md-editor-container :deep(.md-editor-preview) {
	background-color: #fff;
}

/* 暗黑模式样式 */
[data-theme='dark'] .md-editor-container :deep(.md-editor) {
	border-color: #424242;
	background-color: #1f1f1f;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor:hover) {
	border-color: #606266;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor:focus-within) {
	border-color: #409eff;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-toolbar) {
	border-bottom-color: #424242;
	background-color: #262626;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-content) {
	background-color: #1f1f1f;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-input) {
	background-color: #1f1f1f;
	color: #e5eaf3;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-preview) {
	background-color: #1f1f1f;
	color: #e5eaf3;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-preview h1),
[data-theme='dark'] .md-editor-container :deep(.md-editor-preview h2),
[data-theme='dark'] .md-editor-container :deep(.md-editor-preview h3),
[data-theme='dark'] .md-editor-container :deep(.md-editor-preview h4),
[data-theme='dark'] .md-editor-container :deep(.md-editor-preview h5),
[data-theme='dark'] .md-editor-container :deep(.md-editor-preview h6) {
	color: #e5eaf3;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-preview p) {
	color: #cfd3dc;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-preview code) {
	background-color: #2f2f2f;
	color: #e5eaf3;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-preview pre) {
	background-color: #2f2f2f;
	border-color: #424242;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-preview blockquote) {
	border-left-color: #424242;
	background-color: #262626;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-preview table) {
	border-color: #424242;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-preview th),
[data-theme='dark'] .md-editor-container :deep(.md-editor-preview td) {
	border-color: #424242;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-preview th) {
	background-color: #262626;
}

[data-theme='dark'] .md-editor-container :deep(.md-editor-preview td) {
	background-color: #1f1f1f;
}

/* PDF导出按钮样式 */
.md-editor-container :deep(.md-toolbar-item-pdf) {
	color: #409eff;
}

.md-editor-container :deep(.md-toolbar-item-pdf:hover) {
	background-color: rgba(64, 158, 255, 0.1);
}

[data-theme='dark'] .md-editor-container :deep(.md-toolbar-item-pdf) {
	color: #409eff;
}

[data-theme='dark'] .md-editor-container :deep(.md-toolbar-item-pdf:hover) {
	background-color: rgba(64, 158, 255, 0.2);
}

/* 自定义PDF导出按钮样式 */
.md-editor-container :deep(.md-toolbar-item-pdfExport) {
	color: #e74c3c;
	cursor: pointer;
}

.md-editor-container :deep(.md-toolbar-item-pdfExport:hover) {
	background-color: rgba(231, 76, 60, 0.1);
}

[data-theme='dark'] .md-editor-container :deep(.md-toolbar-item-pdfExport) {
	color: #e74c3c;
}

[data-theme='dark'] .md-editor-container :deep(.md-toolbar-item-pdfExport:hover) {
	background-color: rgba(231, 76, 60, 0.2);
}
</style>
